<?php
/**
 * Created by 无所谓已
 * User: Administrator
 * Date: 2025-08-22
 * Time: 22:34
 */

namespace plugin\csauto\app\process;


use plugin\csauto\app\model\TorrentReleaseModel;
use plugin\csauto\app\model\TorrentTaskModel;
use plugin\csauto\app\service\downloader\DownloaderWorkService;
use support\Log;
use Workerman\Crontab\Crontab;
use Workerman\Timer;

/**
 * Class TaskReleaseProcess
 * 步骤7
 * 进行发布站任务的 发布操作
 * 发布完成后进行 种子的做种推送操作
 *
 * @package plugin\csauto\app\process
 */
class TaskReleaseProcess
{
    // 定时器句柄/ID
    protected $timer;
    protected $wechatTimer;
    protected $torrentTaskMaxNum = 2;
    protected $maxTorrentsPerSite = 5; // 单个站点单次最多发布的种子数量
    protected $torrentReleaseInterval = 5; // 每个种子发布之间的间隔(秒)
    protected $maxTasksPerDownloader = 10; // 每个下载器单次最多处理的任务数量

    // 时间间隔 (单位: 秒, 默认5秒)
    protected $interval = 30;

    public function onWorkerStart()
    {
        if (getenv('WORK_DEBUG')) return true;
        $this->timer = Timer::add($this->interval, function () {
            try {
                // 这里执行系统预设的定时任务事件
                $this->run();
            } catch (\Throwable $e) {
                // 构建完整的错误信息
                $errorMessage = "ERROR[TaskReleaseProcess]:" . PHP_EOL;
                $errorMessage .= "Message: " . $e->getMessage() . PHP_EOL;
                $errorMessage .= "File: " . $e->getFile() . PHP_EOL;
                $errorMessage .= "Line: " . $e->getLine() . PHP_EOL;
                $errorMessage .= "Code: " . $e->getCode() . PHP_EOL;
                $errorMessage .= "Trace:" . PHP_EOL . $e->getTraceAsString() . PHP_EOL;

                echo $errorMessage;
            }
        });

        return true;
    }

    public function run()
    {
        addlog('任务-发布任务', 'start');
        
        /*检查未完成的任务情况 - 按站点和下载器进行分组处理*/
        // 获取所有待发布的任务
        $pendingTasks = TorrentReleaseModel::where('status', 1)
            ->orderBy('updated_at')
            ->limit(100)
            ->get();
        
        // 先按站点分组，每个站点最多取5个任务
        $tasksBySite = [];
        foreach ($pendingTasks as $task) {
            $siteId = $task->site_id;
            
            if (!isset($tasksBySite[$siteId])) {
                $tasksBySite[$siteId] = [];
            }
            
            // 每个站点最多取5个任务
            if (count($tasksBySite[$siteId]) < $this->maxTorrentsPerSite) {
                $tasksBySite[$siteId][] = $task;
            }
        }
        
        // 再按下载器分组任务
        $tasksByDownloader = [];
        foreach ($tasksBySite as $siteId => $siteTasks) {
            foreach ($siteTasks as $task) {
                $downloaderId = $task->downloader_id;
                
                if (!isset($tasksByDownloader[$downloaderId])) {
                    $tasksByDownloader[$downloaderId] = [];
                }
                
                $tasksByDownloader[$downloaderId][] = $task;
            }
        }
        
        // 对每个下载器执行发布任务
        $totalProcessed = 0;
        $siteTaskCounts = []; // 记录每个站点实际发布的任务数量
        
        foreach ($tasksByDownloader as $downloaderId => $tasks) {
            addlog('TaskReleaseProcess', "下载器ID：{$downloaderId}，待处理任务数：" . count($tasks));
            
            // 每个下载器处理最多指定数量的任务
            $downloaderProcessed = 0;
            /** @var TorrentReleaseModel $item */
            foreach ($tasks as $item) {
                if ($downloaderProcessed >= $this->maxTasksPerDownloader) {
                    break;
                }
                
                addlog('TaskReleaseProcess', "releaseTask任务ID：{$item['id']}，站点ID：{$item->site_id}，下载器ID：{$downloaderId}-开始");
                try {
                    $code = DownloaderWorkService::releaseTask($item);
                    
                    // 更新该站点已处理的任务计数
                    if (!isset($siteTaskCounts[$item->site_id])) {
                        $siteTaskCounts[$item->site_id] = 0;
                    }
                    $siteTaskCounts[$item->site_id]++;
                    
                    if ($code != 99) {
                        $downloaderProcessed++;
                        $totalProcessed++;
                    }
                    
                    addlog('TaskReleaseProcess', "releaseTask任务ID：{$item['id']}-结束，返回码：{$code}，站点ID：{$item->site_id}已发布：{$siteTaskCounts[$item->site_id]}个");
                    
                    // 在每个种子发布之间增加间隔缓冲（如果该站点还有更多任务要处理）
                    if ($siteTaskCounts[$item->site_id] < $this->maxTorrentsPerSite && $siteTaskCounts[$item->site_id] < count($tasksBySite[$item->site_id])) {
                        addlog('TaskReleaseProcess', "等待{$this->torrentReleaseInterval}秒后继续发布下一个种子");
                        sleep($this->torrentReleaseInterval);
                    }
                } catch (\Throwable $e) {
                    addlog('TaskReleaseProcess', "releaseTask任务ID：{$item['id']}-异常：{$e->getMessage()}");
                    $item->updated_at = date('Y-m-d H:i:s');
                    $item->save();
                }
            }
        }
        
        addlog('TaskReleaseProcess', "本次循环共处理 {$totalProcessed} 个发布任务，涉及 " . count($siteTaskCounts) . " 个不同站点");
        
        // 种子推送操作已拆分到 TaskPushTorrentProcess 独立进程中处理
        
        return '任务调用：' . date('Y-m-d H:i:s') . "\n";
    }

    /**
     * 停止/删除定时器
     *
     * @return bool
     */
    public function stop()
    {
        return Timer::del($this->timer);
    }

}